package com.xlh.service.courseTest.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.xlh.dao.course.helper.TheoryLearnTimeMapperHelper;
import com.xlh.dao.courseTest.PracticeMapperExt;
import com.xlh.dao.courseTest.TheoryLearnTimeMapper;
import com.xlh.dto.course.TheoryChapterLeanTimeStatisticsDTO;
import com.xlh.dto.courseTest.experiment.TheoryChapterStatisticsExportDTO;
import com.xlh.dto.courseTest.practice.PracticeExtDTO;
import com.xlh.dto.user.UserInfoDTO;
import com.xlh.enums.course.ChapterTypeEnum;
import com.xlh.enums.courseTest.JudgementEnum;
import com.xlh.param.course.TheoryChapterLeanTimeStatisticsParam;
import com.xlh.param.course.TheoryLeanTimeStatisticsParam;
import com.xlh.param.course.TheoryVideoStatisticsParam;
import com.xlh.pojo.course.TheoryLearnTimeStatistics;
import com.xlh.pojo.user.UserClass;
import com.xlh.service.courseTest.TheoryService;
import com.xlh.service.user.UserService;
import com.xlh.support.quiz.service.QuizService;
import com.xlh.util.BeanUtil;
import com.xlh.util.CellStyleUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellStyle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sy
 * 理论课接口实现
 */
@Service
public class TheoryServiceImpl implements TheoryService {


    @Autowired
    private TheoryLearnTimeMapper theoryLearnTimeMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private TheoryLearnTimeMapperHelper theoryLearnTimeMapperHelper;

    @Autowired
    private ChapterStatisticsExcelExportImpl chapterStatisticsExcelExportImpl;

    @Autowired
    private PracticeMapperExt practiceMapperExt;

    @Autowired
    private QuizService quizService;




    @Override
    public void saveTheoryVideoTime(TheoryVideoStatisticsParam theoryVideoStatisticsParam) {

        BigDecimal sumTimePara = theoryVideoStatisticsParam.getVideoSumTime();
        BigDecimal videoTimeParam = theoryVideoStatisticsParam.getVideoTime();
        theoryVideoStatisticsParam.setCreateTime(DateUtil.date());
        synchronized (TheoryServiceImpl.class){

            TheoryLearnTimeStatistics theoryLearnTimeStatisticsParam = BeanUtil.transform(TheoryLearnTimeStatistics.class,theoryVideoStatisticsParam);
            TheoryLearnTimeStatistics theoryVideoStatistics = theoryLearnTimeMapper.findQueryTheoryVideoByChapterId(theoryLearnTimeStatisticsParam);
            if (theoryVideoStatistics != null) {
                BigDecimal sumTime = theoryVideoStatistics.getVideoSumTime();
                BigDecimal videoTime = theoryVideoStatistics.getVideoTime();
                // 表示还未点开视频从学习时长中进来的
                if(sumTime == null || videoTime == null){
                    theoryLearnTimeMapper.updateTheoryVideo(theoryVideoStatisticsParam);
                    return;
                }
                if (sumTime.compareTo(sumTimePara) == 0) {
                    if (videoTimeParam.compareTo(videoTime) == 1) {
                        theoryLearnTimeMapper.updateTheoryVideo(theoryVideoStatisticsParam);
                    }
                } else {
                    theoryLearnTimeMapper.deleteTheoryVideo(theoryVideoStatisticsParam);
                    theoryLearnTimeMapper.insertTheoryVideo(theoryLearnTimeStatisticsParam);
                }
            } else {
                theoryLearnTimeMapper.insertTheoryVideo(theoryLearnTimeStatisticsParam);
            }
        }

    }

    @Override
    public String theoryVideoIsFinal(TheoryVideoStatisticsParam theoryVideoStatisticsParam) {

        String result = String.valueOf(JudgementEnum.NO.getValue());
        TheoryLearnTimeStatistics searchParam = BeanUtil.transform(TheoryLearnTimeStatistics.class, theoryVideoStatisticsParam);
        TheoryLearnTimeStatistics queryExperimentByTask = theoryLearnTimeMapper.findQueryTheoryVideoByChapterId(searchParam);
        if (queryExperimentByTask != null) {
            BigDecimal videoTime = queryExperimentByTask.getVideoTime();
            BigDecimal videoSumTime = queryExperimentByTask.getVideoSumTime();
            if(theoryVideoStatisticsParam.getVideoSumTime().compareTo(videoSumTime) == 0){
                if (videoTime.equals(videoSumTime)) {
                    return String.valueOf(JudgementEnum.YES.getValue());
                }
            }
        }
        return result;
    }

    /**
     * 学习时长
     * @param theoryLeanTimeStatisticsParam
     */
    @Override
    public void theoryLearnTime(TheoryLeanTimeStatisticsParam theoryLeanTimeStatisticsParam) {

        // 查询之前是否有记录
        TheoryLearnTimeStatistics theoryVideoStatisticsParam = BeanUtil.transform(TheoryLearnTimeStatistics.class, theoryLeanTimeStatisticsParam);
        TheoryLearnTimeStatistics theoryVideoStatistics = theoryLearnTimeMapper.findQueryTheoryVideoByChapterId(theoryVideoStatisticsParam);

        if(Objects.isNull(theoryVideoStatistics)){
            theoryLearnTimeMapper.insertTheoryVideo(theoryVideoStatisticsParam);
        }else{
            // 增加累计时长
            Long learnTime = theoryVideoStatistics.getLearnTime();
            Long sumLearnTime = learnTime + theoryLeanTimeStatisticsParam.getLearnTime();
            theoryVideoStatistics.setLearnTime(sumLearnTime);
            theoryLearnTimeMapper.updateTheoryLearnTime(theoryVideoStatistics);
        }
    }

    @Override
    public List<TheoryLearnTimeStatistics> findVideoSumInfo(Long courseId, Long classId, List<Long> userIds, List<Long> chapterIds) {

        List<TheoryLearnTimeStatistics> videoSumInfos = theoryLearnTimeMapper.findVideoSumInfo(courseId, classId, userIds, chapterIds);
        List<TheoryLearnTimeStatistics> collect = userIds.stream().map(userid -> new TheoryLearnTimeStatistics(courseId, classId, userid)).collect(Collectors.toList());
        Function<TheoryLearnTimeStatistics, String> getFunctionKey = timeStatistics -> String.valueOf(timeStatistics.getUserId());
        Map<String, List<TheoryLearnTimeStatistics>> mapKey = videoSumInfos.stream().collect(Collectors.groupingBy(getFunctionKey));
        CopyOnWriteArrayList<TheoryLearnTimeStatistics> copyTheoryLearnTimeStatistics = Lists.newCopyOnWriteArrayList(collect);
        for (TheoryLearnTimeStatistics copyTheoryLearnTimeStatistic : copyTheoryLearnTimeStatistics) {
            String key = getFunctionKey.apply(copyTheoryLearnTimeStatistic);
            List<TheoryLearnTimeStatistics> theoryLearnTimeStatistics = mapKey.get(key);
            if(theoryLearnTimeStatistics != null){
                copyTheoryLearnTimeStatistics.remove(copyTheoryLearnTimeStatistic);
                copyTheoryLearnTimeStatistics.addAll(theoryLearnTimeStatistics);
            }
        }
        return copyTheoryLearnTimeStatistics;
    }

    @Override
    public List<TheoryChapterLeanTimeStatisticsDTO> chapterLearnTime(TheoryChapterLeanTimeStatisticsParam theoryLeanTimeParam) {

        List<TheoryChapterLeanTimeStatisticsDTO> list = Lists.newArrayList();
        // 1. 查询当前课程下的所有学生信息
        List<UserInfoDTO> userInfoDTOS = userService.queryDefaultClassUser(theoryLeanTimeParam.getCourseId());
        theoryLeanTimeParam.setUserInfos(userInfoDTOS);

        // 2. 获取所有学生
        List<TheoryChapterLeanTimeStatisticsDTO> result = userInfoDTOS.stream().map(userInfo -> {
            TheoryChapterLeanTimeStatisticsDTO theoryLearnTime = new TheoryChapterLeanTimeStatisticsDTO();
            theoryLearnTime.setUserId(userInfo.getId()).setUserName(userInfo.getName()).setCourseId(theoryLeanTimeParam.getCourseId());
            theoryLearnTime.setChapterId(theoryLeanTimeParam.getChapterId()).setVideoTime(new BigDecimal("0")).setLearnTime(0L);
            theoryLearnTime.setLearnTimeHour(0d).setVideoTimeHour(BigDecimal.valueOf(0d));
            return theoryLearnTime;
        }).collect(Collectors.toList());

        // 3. 获取所有学生
        List<TheoryLearnTimeStatistics> records = Lists.newArrayList();
        if(CollectionUtil.isNotEmpty(theoryLeanTimeParam.getUserInfos())){
            records = theoryLearnTimeMapper.findLearnTimeStatisticsByUserIds(theoryLeanTimeParam);
        }
        List<TheoryChapterLeanTimeStatisticsDTO> dtoRecords = BeanUtil.batchTransform(TheoryChapterLeanTimeStatisticsDTO.class, records);
        dtoRecords.forEach(dtoRecord -> {
            dtoRecord.setVideoTimeHour();
            dtoRecord.setLearnTimeHour();
            dtoRecord.setVideoTimeStr();
            dtoRecord.setLearnTimeStr();
        });

        Function<TheoryChapterLeanTimeStatisticsDTO, String> function = (x -> x.getCourseId() + String.valueOf(x.getChapterId()) + x.getUserId());
        Map<String, List<TheoryChapterLeanTimeStatisticsDTO>> groupByResult = dtoRecords.stream().collect(Collectors.groupingBy(function));

        // 4.用数据库的记录覆盖之前的用户信息
        for (TheoryChapterLeanTimeStatisticsDTO leanTimeStatisticsDTO : result) {

            String mapKey = function.apply(leanTimeStatisticsDTO);
            List<TheoryChapterLeanTimeStatisticsDTO> record = groupByResult.get(mapKey);
            leanTimeStatisticsDTO.setVideoTimeHour();
            leanTimeStatisticsDTO.setLearnTimeHour();
            leanTimeStatisticsDTO.setVideoTimeStr();
            leanTimeStatisticsDTO.setLearnTimeStr();
            if(null == record){
                list.add(leanTimeStatisticsDTO);
            }else{
                record.forEach(temp -> temp.setUserName(leanTimeStatisticsDTO.getUserName()));
                list.addAll(record);
            }
        }
        // 对学习总时长进行排序
        list.sort(Comparator.comparing(TheoryChapterLeanTimeStatisticsDTO::getLearnTime).reversed());

        return list;
    }

    @Override
    public HSSFWorkbook exportChapterTheory(Long chapterId, Long classId,  List<UserInfoDTO> userInfoDTOS,
                                            List<UserClass> studentInfos, String slogan) {

        List<TheoryChapterStatisticsExportDTO> data = getTheoryChapterStatisticsExportDTOS(chapterId, userInfoDTOS, studentInfos);
        // 5. 填充数据
        HSSFWorkbook workBook = chapterStatisticsExcelExportImpl.getWorkBook(ChapterTypeEnum.THEORY, slogan);
        HSSFSheet sheet = workBook.getSheetAt(0);
        CellStyle cellStyle = CellStyleUtils.createCellStyle(workBook);

        chapterStatisticsExcelExportImpl.loadingData(sheet , data,  Lists.newArrayList("userId"), cellStyle);

        return workBook;
    }

    @Override
    public List<TheoryChapterStatisticsExportDTO> getTheoryChapterStatisticsExportDTOS(Long chapterId, List<UserInfoDTO> userInfoDTOS, List<UserClass> studentInfos) {

        List<TheoryChapterStatisticsExportDTO> lists = userInfoDTOS.stream().map(userInfo -> {
            TheoryChapterStatisticsExportDTO dto = new TheoryChapterStatisticsExportDTO();
            dto.setUserId(userInfo.getId());
            dto.setName(userInfo.getName());
            dto.setUserNumber(userInfo.getUserNumber());
            return  dto;
        }).collect(Collectors.toList());

        List<Long> userClassIds = studentInfos.stream().map(UserClass::getId).collect(Collectors.toList());

        List<Long> userIds = userInfoDTOS.stream().map(UserInfoDTO::getId).collect(Collectors.toList());
        // 1. 装载实验课程统计
        Map<Long, List<TheoryLearnTimeStatistics>> theoryMap = theoryLearnTimeMapperHelper.findByCondition(chapterId, userIds).stream().collect(Collectors.groupingBy(TheoryLearnTimeStatistics::getUserId));
        // 2. 装载随堂练习分数
        Map<Long, List<PracticeExtDTO>> practiceMap = practiceMapperExt.findPracticeByChapterId(chapterId, userClassIds).stream().collect(Collectors.groupingBy(PracticeExtDTO::getUserId));
        // 3. 装载课程优良的情况
        Map<Long, List<TheoryChapterStatisticsExportDTO>> performanceMap = quizService.getUserPerformanceByChapterId(chapterId, userIds).stream()
                .collect(Collectors.groupingBy(TheoryChapterStatisticsExportDTO::getUserId));
        // 4. 整理Excel 创建表头
        for (TheoryChapterStatisticsExportDTO dto : lists) {
            Long userId = dto.getUserId();
            // 添加默认值
            dto.initProperty();
            // 视频时长装载
            List<TheoryLearnTimeStatistics> theoryLearnTimeStatistics = theoryMap.get(userId);
            if(CollectionUtil.isNotEmpty(theoryLearnTimeStatistics)){
                TheoryLearnTimeStatistics theoryLearnTimeStatistic = theoryLearnTimeStatistics.get(0);
                dto.setLearnTime(BigDecimal.valueOf(theoryLearnTimeStatistic.getLearnTime()));
                dto.setVideoTime(theoryLearnTimeStatistic.getVideoTime());
                dto.setTimeToHours();
            }
            // 随堂练习装载
            List<PracticeExtDTO> practiceExtDTOS = practiceMap.get(userId);
            if(CollectionUtil.isNotEmpty(practiceExtDTOS)){
                PracticeExtDTO practiceExtDTO = practiceExtDTOS.get(0);
                dto.setScore(Long.valueOf(practiceExtDTO.getScore()));
            }
            List<TheoryChapterStatisticsExportDTO> performances = performanceMap.get(userId);
            // 装载课程优良的情况
            if(CollectionUtil.isNotEmpty(performances)){
                TheoryChapterStatisticsExportDTO performance = performances.get(0);
                dto.setExcellent(performance.getExcellent());
                dto.setGood(performance.getGood());
                dto.setPoor(performance.getPoor());
                dto.setCorrect(performance.getCorrect());
                dto.setInCorrect(performance.getInCorrect());
            }
        }
        return lists;
    }


}
